﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

using Emgu.CV;
using Emgu.CV.UI;
using Emgu.CV.Structure;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace VisionTestApp2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private Image<Gray, Byte> _SourceImage;
        private Image<Gray, Byte> _TemplateImage;
 
        private void LoadSourceImage_Click(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog();

            if (openFileDialog.ShowDialog() != true)
                return;

            _SourceImage = new Image<Gray, Byte>(openFileDialog.FileName);

            SourceImage.Source = ToBitmapSource(_SourceImage);

        }

        private void LoadTemplateImage_Click(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog();

            if (openFileDialog.ShowDialog() != true)
                return;

            _TemplateImage = new Image<Gray, Byte>(openFileDialog.FileName);
  
            TemplateImage.Source = ToBitmapSource(_TemplateImage);
        }



        private static Image<Gray, byte> RotateImage(Image<Gray, byte> image, double angle)
        {
            var transform = new RotationMatrix2D<double>(new System.Drawing.PointF(image.Width / 2, image.Height / 2), angle, 1);
            var data = image.WarpAffine(transform, Emgu.CV.CvEnum.INTER.CV_INTER_AREA, Emgu.CV.CvEnum.WARP.CV_WARP_FILL_OUTLIERS, new Gray(0));
            return data;
        }

        /// <summary>
        /// Delete a GDI object
        /// </summary>
        /// <param name="o">The poniter to the GDI object to be deleted</param>
        /// <returns></returns>
        [DllImport("gdi32")]
        private static extern int DeleteObject(IntPtr o);

        /// <summary>
        /// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source
        /// </summary>
        /// <param name="image">The Emgu CV Image</param>
        /// <returns>The equivalent BitmapSource</returns>
        public static BitmapSource ToBitmapSource(IImage image)
        {
            using (System.Drawing.Bitmap source = image.Bitmap)
            {
                IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap

                BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    ptr,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

                DeleteObject(ptr); //release the HBitmap
                return bs;
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = this;
        }

        public void NotifyPropertyChanged(string property)
        {
            if (PropertyChanged!=null)
                PropertyChanged(this,new PropertyChangedEventArgs(property));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void DoCorrelation_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();

            s.Start();
            Pose = PyramidMatch.FindPose(_SourceImage,_TemplateImage);
            s.Stop();

            var outputImage = _SourceImage.Clone();
            var targetSize = _TemplateImage.Size;
            outputImage.Draw(new System.Drawing.Rectangle(new System.Drawing.Point((int)Pose.X, (int)Pose.Y), targetSize), new Gray(255), 1);
            ResultBasicImage.Source = ToBitmapSource(outputImage);

            MessageBox.Show("Time taken: " + s.ElapsedMilliseconds + " ms");
        }

        

        private EstimatedPose _Pose;
        public EstimatedPose Pose
        {
            get
            {
                return _Pose;
            }
            set
            {
                _Pose = value;
                NotifyPropertyChanged("Pose");
            }
        }

        private void DoForwardAdditive_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();

            s.Start();
            Pose = ForwardsAdditive.FindPose(_SourceImage, _TemplateImage, Pose);
            s.Stop();

            var outputImage = _SourceImage.Clone();
            var targetSize = _TemplateImage.Size;
            outputImage.Draw(new System.Drawing.Rectangle(new System.Drawing.Point((int)Pose.X, (int)Pose.Y), targetSize), new Gray(255), 1);
            ResultBasicImage.Source = ToBitmapSource(outputImage);

            MessageBox.Show("Time taken: " + s.ElapsedMilliseconds + " ms");
        }
    }
}
